package com.chuangke.quartz.job;

import com.chuangke.common.utils.SpringContextUtil;
import com.chuangke.quartz.constant.ScheduleConstants;
import com.chuangke.quartz.entity.SysJob;
import com.chuangke.quartz.entity.SysJobLog;
import com.chuangke.quartz.service.SysJobLogService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.Date;

/**
 * 抽象quartz调用
 *
 */
public abstract class AbstractQuartzJob implements Job {

	private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);

	/**
	 * 线程本地变量
	 */
	private static final ThreadLocal<Date> threadLocal = new ThreadLocal<>();

	@Override
	public void execute(JobExecutionContext context) {
		SysJob sysJob = new SysJob();
		BeanUtils.copyProperties(context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES), sysJob);
		try {
			before(context, sysJob);
			if (sysJob != null) {
				doExecute(context, sysJob);
			}
			after(context, sysJob, null);
		} catch (Exception e) {
//			log.error("任务执行异常  - ：", e);
			log.error("任务执行异常  - ：", e.getCause());
			after(context, sysJob, e.getCause()==null ? e : e.getCause());
		}
	}

	/**
	 * 执行前
	 *
	 * @param context 工作执行上下文对象
	 * @param sysJob  系统计划任务
	 */
	protected void before(JobExecutionContext context, SysJob sysJob) {
		threadLocal.set(new Date());
	}

	/**
	 * 执行后
	 *
	 * @param context 工作执行上下文对象
	 * @param sysJob  系统计划任务
	 */
	protected void after(JobExecutionContext context, SysJob sysJob, Throwable e) {
		Date startTime = threadLocal.get();
		threadLocal.remove();

		final SysJobLog sysJobLog = new SysJobLog();
		sysJobLog.setJobId(sysJob.getId());
		sysJobLog.setName(sysJob.getName());
		sysJobLog.setJobGroup(sysJob.getJobGroup());
		sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
		sysJobLog.setStartTime(startTime);
		sysJobLog.setStopTime(new Date());
		long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
		sysJobLog.setMessage(sysJobLog.getName() + " 总共耗时：" + runMs + "毫秒");
		if (e != null) {
			sysJobLog.setStatus(ScheduleConstants.FAIL);
			String errorMsg = StringUtils.substring(e.getMessage(), 0, 2000);
			sysJobLog.setExceptionInfo(errorMsg);
		} else {
			sysJobLog.setStatus(ScheduleConstants.SUCCESS);
		}

		// 写入数据库当中
		SpringContextUtil.getBean(SysJobLogService.class).save(sysJobLog);
	}

	/**
	 * 执行方法，由子类重载
	 *
	 * @param context 工作执行上下文对象
	 * @param sysJob  系统计划任务
	 * @throws Exception 执行过程中的异常
	 */
	protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
}
